# -*- coding: utf-8 -*

""" A Village is an area where varoius sprites can be placed in

Currently we have:
Center / Well
Crop Field
House
"""

import area
import grid
import os
import pygame

class Village (area.Area):
    """ a Village is a container for houses and crop-fields and 
        keeps record of its residents
        Tip: Use updateResidents every time you added and taged a resident
    """
    def __init__(self, grid, id, center):
        super (Village, self).__init__(grid, "village", id, center)
        self._homes = []
        self._residents = []
        self._foodstock = 0
        
        #self.tPosTi = (0,0)          # top left
        #self.tSizeTi = (0,0)
        #now: rect
    def __repr__(self):
        return "<Village '"+self.name+"'>"


     # -> see area : area_rectangle / update_area_tagging
     
#    def tagVillageArea(self, tPosTi, tSizeTi):
#        """create a village: tag a area of tiles with the viallge name""" 
#        self.tPosTi = tPosTi
#        self.tSizeTi = tSizeTi
#        xt = tPosTi[0]
#        yt = tPosTi[1]
#        for h in xrange(0, tSizeTi[1]):
#            for w in xrange(0,tSizeTi[1]):
#                t = self.grid.getTileAtTi ((xt+w, yt+h))
#                if t != None: 
#                    self.grid.register (t, self) 
        

    def set_village_center (self, reshelper):
        " load and place sprite in the vialage center"
        c = self.rect.center
        t = self._grid.get_tile_at_tilepos (c)
        res = reshelper.loadBuildingTar (os.path.join("res","gfx","well.tar.gz"),t.rect.topleft)
        print res
        well = VillageCenter (self._grid, t.rect.topleft, res[0])
        well.depth = res[1]
        reshelper.registerUsedTilesFromSurface (res[0], t.rect.topleft, well)
        self._homes.append(well)
        self._grid.register (well, self.name)
        self._grid.register (t, well)
        # register Well in village
        self._grid.register (self, well)
    
    def isSpotGoodToBuild (self, tile, rRect):
        """
        checks if we build at "tile" we would collide with other homes or fields
        """
        tPosPi = tile.rPosPi.topleft
        rRect.topleft = tPosPi
        collide = False
        for h in self._homes:
            r = h.rRect
            r.topleft = h.tPosPi
            if r.colliderect (rRect):
                collide = True
        return not collide
        
        
    
    def getFreeToBuildTilesInVillage(self):
        """
        return all tiles as list which are not occupied by something
        """
        obj = self.getByType(cTile)
        if obj == []: return []
        objFil = []
        for o in obj:
            tags = self.grid.getObjsForTag (o)
            append = True
            for t in tags:
                if isinstance(t, cHome) \
                or isinstance (t, cVillageCenter) \
                or isinstance (t, cCropField):
                    append = False
            if append == True:   
                objFil.append(o)
        #print "getFreeToBuildTilesInVillage in: ", len(obj), "out:", len(objFil)
        return objFil
    
        
    def addHome (self, reshelper, tPosPi=None):
        """
        create and place a house and a crop field in the village
        if tPosPi is None: placement will be random and tries not to overlap
        """
        if tPosPi == None:
            obj = self.getFreeToBuildTilesInVillage()
            if obj == []: return
            iterMax = 100
            c = 0
            while c < iterMax:
                t = obj[rndint(len(obj))]
                rImgSize = reshelper.prefetchImageSize (os.path.join("res","gfx","house1.tar.gz"))
                if self.isSpotGoodToBuild (t, rImgSize) == True: 
                    break
                c+=1
            if c == iterMax:
                print "addHome / Warning: Build overlay in village",self,"occured (itermax reached)"
            tPosPi = t.rPosPi.topleft
        # continue         
        res = reshelper.loadBuildingTar (os.path.join("res","gfx","house1.tar.gz"),tPosPi)
        t = self.grid.getTileAtPi (tPosPi)
        home = cHome (tPosPi, res[0], res[1], self.zBuffer)
        # Tag every space occupied by the img (including transparent) with home
        # this is used to avoid others building here
        reshelper.registerUsedTilesFromSurface (res[0], tPosPi, home)
        self._homes.append(home)
        self.grid.register (home, self.name)
        self.grid.register (t, home)
        # register Home in village
        self.grid.register (self, home)
        return home
    
    def addField (self, reshelper, home, tPosPi=None):
        """
        add a field for a home in the village
        if tPosPi is None: placement will be random and tries not to overlap
        """
        if tPosPi == None:
            obj = self.getFreeToBuildTilesInVillage()
            if obj == []: return    
            iterMax = 100
            c = 0
            while c < iterMax:
                t = obj[rndint(len(obj))]
                rImgSize = reshelper.prefetchImageSize (os.path.join("res","gfx","field.tar.gz"))
                if self.isSpotGoodToBuild (t, rImgSize) == True: 
                    break
                c+=1
            if c == iterMax:
                print "addField / Warning: Build overlay in village",self,"occured (itermax reached)"
            tPosPi = t.rPosPi.topleft
        res = reshelper.loadBuildingTar (os.path.join("res","gfx","field.tar.gz"),tPosPi)
        t = self.grid.getTileAtPi (tPosPi)
        field = cCropField (tPosPi, res[0], res[1], self.zBuffer)
        reshelper.registerUsedTilesFromSurface (res[0], tPosPi, field)
        self._homes.append(field)
        self.grid.register (field, self.name)
        self.grid.register (t, field)
        # register Field in village
        self.grid.register (self, field)
        home.setField(field)
        home.addResident (self.grid, self.zBuffer, self) 
        self.updateResidents()        
    def getByType (self, type):
        """ Return all objects instance of "type" e.g. cHuman, cTile which are tagged with name of village"""
        obj = self.grid.getObjsForTag (self)
        return [o for o in obj if isinstance (o, type)]
    def updateResidents(self):
        """ update local store for quick access to viallage residents -> call after changing residents!"""
        self._residents = self.getByType (humanoids.cWoodChopper)
    def getResidents(self):
        return self._residents
    def addResident (self):
        """ add a resident to a home and set his proerties """
        # was muss getan werden damit er im harvest state zu seinem field und dann zu seinem home laufen kann
        pass
    def growVillage (self):
        """check if growing conditions are met / control birth / death rates and grow village accordingly
            to be called periodically from the main loop
        """
        pass
    def addFood (self, amount):
        """ add Food to the viallage food stock"""
        self._foodstock += amount
    def subFood (self, amount):
        """remove food from village food stock, returns the amount taken"""
        self._foodstock -= amount
        if self._foodstock - amount < 0:
            self._foodstock = 0
            return self._foodstock
        return amount
    def getFood (self):
        "get amount of food in village stock"""
        return self._foodstock
  
  
# SPRITE-Classes  
    
    
# Types for village     
class CropField(grid.Gridsprite):
    def __init__(self, tPosPi=(0,0), img=None, depth=0, zBuffer=None):
        img = img.convert()
        img.set_colorkey ((255,0,255,255), pygame.RLEACCEL)
        cSprite.__init__(self, tPosPi, img, depth, zBuffer)
    # Was das CropField wissen /machen könnte:
    # Seine Wachstumszustand  oder die Nahrung, die es abwirft, reifegrad usw.
    # oder sein alter ...
    # sein besitzer
    # es könnte eine funktion haben wir "harvest" wo es einen teil seiner anhrung rausrückt
    # damit ein männchen es abgreifen kann
    # damit könnte das männchen auch mitbekommen, wenn das feld leer ist
    # es könnte eine grow funmktion haben, die periodisch aufgerufen wird (z.b. pro spieltag oder monat
    # und nahrung (je nach jahreszeit hinzufügt oder verwirft -> z,B, im Winter auf 0 setzt und die 
    # max. Menge der Nahrung an der größe des FEldes festmachen)
    def __repr__(self):
        return "<cCropField at:" + str((int(self.tPosPi[0]),int(self.tPosPi[1]))) + "/"+str(self._depth)+">"                   

                        
class VillageCenter(grid.Gridsprite):
    def __init__(self, grid, pos=(0,0), img=None):
        super (VillageCenter, self).__init__(grid) 
        self.img = img.convert()
        self.img.set_colorkey ((255,0,255,255), pygame.RLEACCEL)
        self.rect.topleft = pos
        
    def __repr__(self):
        return "<VilageCenter >"                   
    def draw (self, screen, optional_ignore=None):
        screen.blit (self.img, self._grid.g2s(self.rect.topleft))
 

class Home (grid.Gridsprite):
    def __init__(self, tPosPi=(0,0), img=None, depth=0, zBuffer=None):
        img = img.convert()
        img.set_colorkey ((255,0,255,255), pygame.RLEACCEL)
        cSprite.__init__(self, tPosPi, img, depth, zBuffer)
        self._field = None
    def __repr__(self):
        return "<cHome at:" + str((int(self.tPosPi[0]),int(self.tPosPi[1]))) + "/"+str(self._depth)+">" 
    def setField (self, field): 
        # TODO: sollte das Field hier nicht auch in die Registrirung geschrieben werden?
        self._field = field
    def getField (self): return self._field
    def getResidents (self, grid):
        """return all cHumans tagged with (my)self"""
        obj = grid.getObjectsByTag (self)
        return [o for o in obj if isinstance (o, cHuman)]
    def addResident (self, grid, zBuffer, village):
        """crete a new resident for this home"""
        tile = grid.getTileAtPi(self.tPosPi)
        dState = {"idle": "callbackIdle",
                  "run": "callbackRun",
                  "walk": "callbackWalk",
                  "harvest": "callbackHarvest"}
        obj = humanoids.cWoodChopper(grid, tile.rPosPi.center, None, tile.getZDepth(), zBuffer)    
        #obj.loadResources("johnny", dState)
        obj.setState("idle", "idle")
        x = rndint (10)
        y = rndint (20)
        tile = grid.getTileAtTi((x,y))
        if tile != None:
            obj.setState("walk", "walk", tile) 
            obj.setSpeed(0.5)
            grid.register(obj, tile)
            
        grid.register(obj, village)
        grid.register(obj, self)
        return obj


